package com.spring.theory.bean.beanFactory;

import static com.spring.theory.constant.GeneralConstant.LOG_INFO;

import java.util.Arrays;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 阅读1-1
 * BeanFactory的实现
 * - 控制反转、基本的依赖注入、直至Bean的生命周期的各种功能，都由它的实现类提供
 * <p>
 * - 不会主动调用BeanFactory后处理器
 * - 不会主动添加Bean后处理器
 * - 不会主动初始化单例
 * - 不会解析 ${ },#{ }
 *
 * @author 24373
 * @date 2023/12/23 15:12
 */
@Slf4j
public class TestBeanFactory {
    public static void main(String[] args) {
        //DefaultListableBeanFactory是BeanFactory的一个常用实现类
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        /**
         * 1.bean的定义（class、scope、初始化、销毁）
         * 注：定义bean再交由BeanFactory去创建bean对象（控制反转）
         */
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(BeanFactoryConfig.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("beanFactoryConfig", beanDefinition);

        /**
         * 2.给beanFactory添加一些常用后处理器；但还没运行，起作用
         * 包括 BeanFactoryPostProcessor和 BeanPostProcessor（如：internalConfigurationAnnotationProcessor 可以用来解析注册带注解的bean[@Configuration,@Bean]）
         */
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        log.info(LOG_INFO);
        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(t -> log.info("BeanFactory内BeanDefinitionNames::{}", t));

        /**
         * 3.执行beanFactory后处理器 ； 与bean的定义相关
         * postProcessBeanFactory 是一个用于修改应用程序上下文内部bean工厂的方法；在这个方法被调用时，所有的bean定义都已经被加载到bean工厂中，但是还没有任何bean被实例化。可以在此时修改或添加bean的属性
         */
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(t -> t.postProcessBeanFactory(beanFactory));
        log.info(LOG_INFO);
        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(t -> log.info("BeanDefinitionNames:{}", t));
        log.info(LOG_INFO);

        /**
         * 4.建立beanFactory与bean后处理器的联系 ；针对bean的生命周期的各个阶段提供扩展(构造,依赖注入,初始化,销毁)
         * bean的后处理器来解析@AtuoWire,@Value,@Resource等注解
         * bean后处理器有执行顺序，由order接口控制
         */
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanPostProcessor -> beanFactory.addBeanPostProcessor(beanPostProcessor));
        log.info(LOG_INFO);

        /**
         * 5.预先实例化单例bean
         * beanFactory初始只记录了bean的基本信息，但并没有实例化bean；默认是懒加载的，当bean在使用时，才会创建
         */
        beanFactory.preInstantiateSingletons();

        /**
         * bean1中依赖了bean2，当bean1被beanFactory创建使用的时候，会解析到其中依赖bean2并且使用了@Autowired。所以会调用bean后处理器去解析。完成bean2的构建
         */
        log.info("BeanFactoryBean2:{}", beanFactory.getBean(BeanFactoryBean1.class).getBean2());

    }

    @Configuration
    static class BeanFactoryConfig {

        @Bean
        public BeanFactoryBean1 bean1() {
            return new BeanFactoryBean1();
        }

        @Bean
        public BeanFactoryBean2 bean2() {
            return new BeanFactoryBean2();
        }

    }

    static class BeanFactoryBean1 {
        @Autowired
        private BeanFactoryBean2 bean2;

        public BeanFactoryBean1() {
            log.info("bean1 构造器");
        }

        public BeanFactoryBean2 getBean2() {
            log.info("bean2 获取");
            return this.bean2;
        }
    }

    static class BeanFactoryBean2 {
        public BeanFactoryBean2() {
            log.info("bean2 构造器");
        }
    }

}
